package com.fingard.dsp.bank.directbank.weixin01.domain;


import com.fingard.dsp.bank.directbank.weixin01.domain.common.DomainConfig;
import com.fingard.dsp.bank.directbank.weixin01.domain.common.DomainConstants;
import com.fingard.dsp.bank.directbank.weixin01.domain.common.DomainUtil;
import com.fingard.dsp.bank.directbank.weixin01.domain.entity.SuccessRateData;
import com.fingard.dsp.bank.directbank.weixin01.domain.task.SuccessRateCountTimer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;
import java.util.Timer;

/**
 * 【统计主域名实际请求成功率策略】接口实现
 * @author liujinhui
 */
public class SuccessRateCount extends AbstractDomainService implements IDomainService {

    private static Logger logger = LoggerFactory.getLogger(SuccessRateCount.class);

    private static SuccessRateCount INSTANCE;
    
    // 定时器-上报结果分析开启状态
    private static boolean RESULT_REPORT_TIMER_STATUS;
    // 公众平台上报请求结果
    private static LinkedList<SuccessRateData> RESULT_DATA = new LinkedList<SuccessRateData>();
    // 微信支付上报请求结果
    private static LinkedList<SuccessRateData> RESULT_MCH_DATA = new LinkedList<SuccessRateData>();

    /**
     * 上报结果分析定时器相关
     */
    private static SuccessRateCountTimer successRateCountTask;
    private static Timer successRateCountTimer;

    private SuccessRateCount() {
        super();
        start(this);
    }

    private SuccessRateCount(DomainConfig config) {
        super(config);
        start(this);
    }

    public static synchronized SuccessRateCount getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new SuccessRateCount();
        }
        return INSTANCE;
    }

    /**
     * 以单例模式实例化对象
     * @param config
     * @return
     */
    public static synchronized SuccessRateCount getInstance(DomainConfig conf) {
        if (INSTANCE == null) {
            INSTANCE = new SuccessRateCount(conf);
        }
        return INSTANCE;
    }

    /**
     * 启动上报结果分析定时器，实现主备域名实时切换
     * @return
     */
    private static synchronized void start(SuccessRateCount successRateCount) {
        RESULT_REPORT_TIMER_STATUS = true;
        if (successRateCountTask == null) {
            if (successRateCountTimer == null) {
                successRateCountTimer = new Timer();
            }
            successRateCountTask = new SuccessRateCountTimer(successRateCountTimer, getConfig(), successRateCount);
            int frequency = getConfig().getResultReportFrequency();
            successRateCountTimer.scheduleAtFixedRate(successRateCountTask,
                    DomainConstants.TIMER_DELAY_TIME, frequency);
        }
        logger.info("【统计主域名实际请求成功率策略】定时器启动成功");
    }

    /**
     * 上报请求结果
     * @param reportResult (0:失败,1:成功，必填)
     * @param domain (当前请求域名，必填)
     */
    public void reportResult(DomainConstants.ReportResult reportResult, String domain) {
        if (reportResult != null && !DomainUtil.StringIsEmpty(domain)) {
            SuccessRateData result = new SuccessRateData(reportResult, domain);
            int resultDataMaxSize = getConfig().getResultDataMaxSize();

            if (DomainConstants.API_MCH_WEIXIN_DOMAIN.equals(domain)) {
                addResultData(DomainConstants.DomainType.API_MCH, result,
                        resultDataMaxSize);
            } else if (DomainConstants.API_WEIXIN_DOMAIN.equals(domain)) {
                addResultData(DomainConstants.DomainType.API, result,
                        resultDataMaxSize);
            }
        }
    }
    
    /**
     * 修改定时器开启状态
     * @param value
     */
    public void setTimerStatus(boolean value) {
        RESULT_REPORT_TIMER_STATUS = value;
    }
    
    /**
     * 获取定时器开启状态
     * @return
     */
    public boolean getTimerStatus() {
        return RESULT_REPORT_TIMER_STATUS;
    }
    
    /**
     * 上报请求结果
     * @param domainType
     * @param result
     */
    public synchronized void addResultData(DomainConstants.DomainType domainType, SuccessRateData result,
            int resultDataMaxSize) {
        LinkedList<SuccessRateData> list = getResultData(domainType);
        if (list != null && result != null) {
            list.add(result);
            while (list.size() > resultDataMaxSize) {
                list.removeFirst();
            }
        }
    }
    
    /**
     * 获取主域名上报请求结果
     * @param domainType
     * @return
     */
    public LinkedList<SuccessRateData> getResultData(DomainConstants.DomainType domainType) {
        LinkedList<SuccessRateData> list = null;
        if (DomainConstants.DomainType.API_MCH.equals(domainType)) {
            list = RESULT_MCH_DATA;
        } else if (DomainConstants.DomainType.API.equals(domainType)) {
            list = RESULT_DATA;
        }
        return list;
    }
    
    /**
     * 清理主域名上报请求结果
     * @param domainType
     */
    public void cleanResultData(DomainConstants.DomainType domainType) {
        if (DomainConstants.DomainType.API_MCH.equals(domainType)) {
            RESULT_MCH_DATA.clear();
        } else if (DomainConstants.DomainType.API.equals(domainType)) {
            RESULT_DATA.clear();
        }
    }
}
